<template>
  <div class="registry-container">
    <!-- 头部 -->
    <header class="registry-header">
      <h1>Docker 镜像仓库</h1>
      <p>集中管理您的容器镜像</p>
    </header>

    <!-- 控制栏 -->
    <div class="registry-controls">
      <div class="controls-left">
        <div class="search-box">
          <input
            v-model="searchQuery"
            @input="searchImages"
            type="text"
            placeholder="搜索镜像名称或标签..."
          />
        </div>
        <div class="page-size-selector">
          <label>每页显示：</label>
          <select v-model="pageSize" @change="handlePageSizeChange">
            <option value="10">10</option>
            <option value="20">20</option>
            <option value="50">50</option>
            <option value="100">100</option>
          </select>
        </div>
      </div>
      <div class="controls-right">
        <div class="total-count">
          共 {{ totalImages }} 个镜像
        </div>
        <button
          @click="uploadImage"
          class="upload-btn"
        >
          + 上传镜像
        </button>
      </div>
    </div>

    <!-- 镜像列表容器 -->
    <div class="image-list-container">
      <!-- 表头 -->
      <div class="image-list-header">
        <div>镜像名称</div>
        <div>标签</div>
        <div>大小</div>
        <div>更新时间</div>
        <div>操作</div>
      </div>

      <!-- 加载状态 -->
      <div v-if="loading" class="empty-state">
        <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-4"></div>
        <p>正在加载镜像列表...</p>
      </div>

      <!-- 镜像列表 -->
      <ul v-else-if="paginatedImages.length > 0" class="image-list">
        <template v-for="image in paginatedImages" :key="image.name">
          <li v-for="(tag, index) in (image.tags || ['latest'])" :key="`${image.name}-${tag}`"
              class="image-item">
            <!-- 镜像名称 -->
            <div class="image-name">{{ image.name }}</div>

            <!-- 标签 -->
            <div class="image-tag">{{ tag }}</div>

            <!-- 大小 -->
            <div class="image-size">{{ formatSize(image.size) }}</div>

            <!-- 更新时间 -->
            <div class="image-date">{{ formatTime(image.updatedAt) }}</div>

            <!-- 操作 -->
            <button
              @click="deleteImageTag(image.name, tag)"
              :disabled="deletingImages.has(`${image.name}:${tag}`)"
              class="delete-btn"
              :class="{ 'opacity-50 cursor-not-allowed': deletingImages.has(`${image.name}:${tag}`) }"
            >
              <span v-if="deletingImages.has(`${image.name}:${tag}`)">删除中...</span>
              <span v-else>删除</span>
            </button>
          </li>
        </template>
      </ul>

      <!-- 空状态 -->
      <div v-else class="empty-state">
        <p>未找到匹配的镜像。</p>
      </div>

      <!-- 分页组件 -->
      <div v-if="totalPages > 1" class="pagination-container">
        <div class="pagination-info">
          显示第 {{ (currentPage - 1) * pageSize + 1 }} - {{ Math.min(currentPage * pageSize, totalImages) }} 条，共 {{ totalImages }} 条
        </div>
        <div class="pagination">
          <button
            @click="goToPage(1)"
            :disabled="currentPage === 1"
            class="pagination-btn"
          >
            首页
          </button>
          <button
            @click="goToPage(currentPage - 1)"
            :disabled="currentPage === 1"
            class="pagination-btn"
          >
            上一页
          </button>

          <template v-for="page in visiblePages" :key="page">
            <button
              v-if="page !== '...'"
              @click="goToPage(page)"
              :class="['pagination-btn', { 'active': page === currentPage }]"
            >
              {{ page }}
            </button>
            <span v-else class="pagination-ellipsis">...</span>
          </template>

          <button
            @click="goToPage(currentPage + 1)"
            :disabled="currentPage === totalPages"
            class="pagination-btn"
          >
            下一页
          </button>
          <button
            @click="goToPage(totalPages)"
            :disabled="currentPage === totalPages"
            class="pagination-btn"
          >
            末页
          </button>
        </div>
      </div>
    </div>

    <!-- 镜像详情模态框 -->
    <div v-if="selectedImage" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4" @click="closeImageDetail">
      <div class="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[80vh] overflow-hidden" @click.stop>
        <!-- 模态框头部 -->
        <div class="flex items-center justify-between p-6 border-b border-gray-200">
          <div>
            <h3 class="text-xl font-bold text-gray-900">{{ selectedImage.name }}</h3>
            <p class="text-sm text-gray-500 mt-1">镜像详情信息</p>
          </div>
          <button @click="closeImageDetail" class="p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-lg transition-colors">
            <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
            </svg>
          </button>
        </div>
        
        <!-- 模态框内容 -->
        <div class="p-6 overflow-y-auto max-h-[calc(80vh-120px)]">
          <div class="space-y-6">
            <!-- 基本信息 -->
            <div class="grid grid-cols-2 gap-4">
              <div class="bg-gray-50 rounded-lg p-4">
                <div class="text-sm text-gray-600 mb-1">镜像大小</div>
                <div class="text-lg font-semibold text-gray-900">{{ formatSize(selectedImage.size) }}</div>
              </div>
              <div class="bg-gray-50 rounded-lg p-4">
                <div class="text-sm text-gray-600 mb-1">更新时间</div>
                <div class="text-lg font-semibold text-gray-900">{{ formatTime(selectedImage.updatedAt) }}</div>
              </div>
            </div>
            
            <!-- 可用标签 -->
            <div>
              <h4 class="font-semibold text-gray-900 mb-4">可用标签</h4>
              <div class="flex flex-wrap gap-2">
                <span v-for="tag in selectedImage.tags" :key="tag" class="inline-flex items-center px-3 py-2 rounded-lg text-sm font-medium bg-blue-100 text-blue-800 border border-blue-200">
                  {{ tag }}
                </span>
              </div>
            </div>
            
            <!-- Pull 命令 -->
            <div>
              <h4 class="font-semibold text-gray-900 mb-4">Pull 命令</h4>
              <div class="space-y-3">
                <div v-for="tag in selectedImage.tags" :key="tag" class="bg-gray-50 rounded-lg border p-4">
                  <div class="flex items-center justify-between">
                    <div class="flex-1 mr-4">
                      <div class="text-xs text-gray-500 mb-2">{{ tag }} 标签</div>
                      <code class="text-sm text-gray-800 font-mono break-all">
                        docker pull {{ registryHost }}/{{ selectedImage.name }}:{{ tag }}
                      </code>
                    </div>
                    <button 
                      @click="copyPullCommand({...selectedImage, tags: [tag]}, $event)"
                      class="flex-shrink-0 px-4 py-2 text-sm bg-blue-600 hover:bg-blue-700 text-white rounded-lg transition-colors"
                      title="复制命令"
                    >
                      复制
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 上传镜像对话框 -->
    <div v-if="showUploadDialog" class="upload-dialog-overlay" @click="cancelUpload">
      <div class="upload-dialog" @click.stop>
        <div class="upload-dialog-header">
          <h3>上传镜像</h3>
          <button @click="cancelUpload" class="close-btn">×</button>
        </div>

        <div class="upload-dialog-content">
          <div class="upload-info">
            <p>支持的文件格式：{{ uploadEnvironment?.supported_formats?.join(', ') || '.tar, .tar.gz' }}</p>
            <p>最大文件大小：{{ formatSize(uploadEnvironment?.max_file_size || 1024*1024*1024) }}</p>
            <p>请选择通过 <code>docker save</code> 命令导出的镜像文件</p>
            <p class="upload-example">示例：<code>docker save -o my-image.tar my-image:latest</code></p>
          </div>

          <div class="file-input-container">
            <input
              type="file"
              id="imageFile"
              accept=".tar,.tar.gz"
              @change="handleFileSelect"
              :disabled="uploading"
              class="file-input"
            />
            <label for="imageFile" class="file-input-label">
              <span v-if="!uploadFile">选择镜像文件</span>
              <span v-else>{{ uploadFile.name }}</span>
            </label>
          </div>

          <div v-if="uploading" class="upload-progress">
            <div class="progress-bar">
              <div class="progress-fill" :style="{ width: uploadProgress + '%' }"></div>
            </div>
            <div class="progress-text">上传中... {{ uploadProgress }}%</div>
          </div>

          <div class="upload-dialog-actions">
            <button
              @click="cancelUpload"
              :disabled="uploading"
              class="cancel-btn"
            >
              取消
            </button>
            <button
              @click="performUpload"
              :disabled="!uploadFile || uploading"
              class="upload-btn-dialog"
            >
              <span v-if="uploading">上传中...</span>
              <span v-else>开始上传</span>
            </button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.registry-container {
  width: 100%;
  margin: 0;
  background-color: #fff;
  border-radius: 10px;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.registry-header {
  background: linear-gradient(135deg, #0066cc, #1e90ff);
  color: white;
  padding: 25px 30px;
  text-align: center;
}

.registry-header h1 {
  font-size: 28px;
  margin-bottom: 10px;
  font-weight: bold;
}

.registry-header p {
  font-size: 16px;
  opacity: 0.9;
}

.registry-controls {
  padding: 25px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  background-color: #e3f2fd;
  border-bottom: 1px solid #ddd;
  flex-wrap: wrap;
  gap: 20px;
}

.controls-left {
  display: flex;
  align-items: center;
  gap: 20px;
  flex: 1;
}

.controls-right {
  display: flex;
  align-items: center;
  gap: 20px;
}

.search-box {
  min-width: 300px;
}

.page-size-selector {
  display: flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}

.page-size-selector label {
  font-size: 14px;
  color: #666;
}

.page-size-selector select {
  padding: 8px 12px;
  border: 1px solid #ccc;
  border-radius: 4px;
  font-size: 14px;
  outline: none;
}

.page-size-selector select:focus {
  border-color: #0066cc;
}

.total-count {
  font-size: 14px;
  color: #666;
  white-space: nowrap;
}

.search-box input {
  width: 100%;
  padding: 12px 15px;
  border: 1px solid #ccc;
  border-radius: 5px;
  font-size: 16px;
  outline: none;
}

.search-box input:focus {
  border-color: #0066cc;
  box-shadow: 0 0 0 2px rgba(0, 102, 204, 0.2);
}

.upload-btn {
  background-color: #28a745;
  color: white;
  border: none;
  padding: 12px 25px;
  border-radius: 5px;
  cursor: pointer;
  font-size: 16px;
  font-weight: bold;
  transition: background-color 0.3s;
  white-space: nowrap;
}

.upload-btn:hover {
  background-color: #218838;
}

.image-list-container {
  padding: 20px;
}

.image-list-header {
  display: grid;
  grid-template-columns: 3fr 1fr 1fr 1fr 0.5fr;
  padding: 15px 20px;
  font-weight: bold;
  background-color: #f8f9fa;
  border-bottom: 2px solid #dee2e6;
}

.image-list {
  list-style: none;
  margin: 0;
  padding: 0;
}

.image-item {
  display: grid;
  grid-template-columns: 3fr 1fr 1fr 1fr 0.5fr;
  padding: 15px 20px;
  border-bottom: 1px solid #eee;
  align-items: center;
  transition: background-color 0.2s;
}

.image-item:hover {
  background-color: #f8f9fa;
}

.image-name {
  font-weight: 500;
  color: #333;
}

.image-tag {
  color: #0066cc;
  font-weight: 500;
  cursor: pointer;
}

.image-tag:hover {
  text-decoration: underline;
}

.image-size, .image-date {
  color: #666;
}

.delete-btn {
  background-color: #dc3545;
  color: white;
  border: none;
  padding: 8px 12px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: background-color 0.3s;
  justify-self: center;
}

.delete-btn:hover {
  background-color: #c82333;
}

.empty-state {
  text-align: center;
  padding: 60px 20px;
  color: #6c757d;
}

.empty-state p {
  font-size: 18px;
}

/* 分页样式 */
.pagination-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-top: 1px solid #eee;
  background-color: #f8f9fa;
}

.pagination-info {
  font-size: 14px;
  color: #666;
}

.pagination {
  display: flex;
  align-items: center;
  gap: 8px;
}

.pagination-btn {
  padding: 8px 12px;
  border: 1px solid #ddd;
  background-color: #fff;
  color: #333;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.2s;
  min-width: 40px;
}

.pagination-btn:hover:not(:disabled) {
  background-color: #f0f0f0;
  border-color: #ccc;
}

.pagination-btn.active {
  background-color: #0066cc;
  color: white;
  border-color: #0066cc;
}

.pagination-btn:disabled {
  background-color: #f5f5f5;
  color: #ccc;
  cursor: not-allowed;
  border-color: #e0e0e0;
}

.pagination-ellipsis {
  padding: 8px 4px;
  color: #666;
  font-size: 14px;
}

/* 上传对话框样式 */
.upload-dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.upload-dialog {
  background: white;
  border-radius: 8px;
  width: 500px;
  max-width: 90vw;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

.upload-dialog-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 24px;
  border-bottom: 1px solid #e5e7eb;
}

.upload-dialog-header h3 {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
  color: #1f2937;
}

.close-btn {
  background: none;
  border: none;
  font-size: 24px;
  color: #6b7280;
  cursor: pointer;
  padding: 0;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
}

.close-btn:hover {
  background: #f3f4f6;
  color: #374151;
}

.upload-dialog-content {
  padding: 24px;
}

.upload-info {
  margin-bottom: 20px;
  padding: 16px;
  background: #f8fafc;
  border-radius: 6px;
  border-left: 4px solid #3b82f6;
}

.upload-info p {
  margin: 0 0 8px 0;
  color: #475569;
  font-size: 14px;
}

.upload-info p:last-child {
  margin-bottom: 0;
}

.upload-info code {
  background: #e2e8f0;
  padding: 2px 6px;
  border-radius: 3px;
  font-family: 'Courier New', monospace;
  font-size: 13px;
}

.upload-example {
  margin-top: 12px;
  padding: 8px;
  background: #f1f5f9;
  border-radius: 4px;
  border-left: 3px solid #10b981;
}

.file-input-container {
  margin-bottom: 20px;
}

.file-input {
  display: none;
}

.file-input-label {
  display: block;
  padding: 12px 16px;
  border: 2px dashed #d1d5db;
  border-radius: 6px;
  text-align: center;
  cursor: pointer;
  transition: all 0.2s;
  color: #6b7280;
  font-size: 14px;
}

.file-input-label:hover {
  border-color: #3b82f6;
  background: #f8fafc;
  color: #3b82f6;
}

.upload-progress {
  margin-bottom: 20px;
}

.progress-bar {
  width: 100%;
  height: 8px;
  background: #e5e7eb;
  border-radius: 4px;
  overflow: hidden;
  margin-bottom: 8px;
}

.progress-fill {
  height: 100%;
  background: #3b82f6;
  transition: width 0.3s ease;
}

.progress-text {
  text-align: center;
  font-size: 14px;
  color: #6b7280;
}

.upload-dialog-actions {
  display: flex;
  gap: 12px;
  justify-content: flex-end;
}

.cancel-btn, .upload-btn-dialog {
  padding: 10px 20px;
  border-radius: 6px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
}

.cancel-btn {
  background: #f3f4f6;
  border: 1px solid #d1d5db;
  color: #374151;
}

.cancel-btn:hover:not(:disabled) {
  background: #e5e7eb;
}

.upload-btn-dialog {
  background: #3b82f6;
  border: 1px solid #3b82f6;
  color: white;
}

.upload-btn-dialog:hover:not(:disabled) {
  background: #2563eb;
}

.upload-btn-dialog:disabled, .cancel-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* 响应式设计 */
@media (max-width: 1024px) {
  .controls-left {
    flex-direction: column;
    align-items: flex-start;
    gap: 15px;
  }

  .controls-right {
    flex-direction: column;
    align-items: flex-end;
    gap: 15px;
  }
}

@media (max-width: 768px) {
  .registry-controls {
    flex-direction: column;
    align-items: stretch;
  }

  .controls-left,
  .controls-right {
    width: 100%;
    flex-direction: column;
    align-items: stretch;
  }

  .search-box {
    min-width: 100%;
  }

  .image-list-header, .image-item {
    grid-template-columns: 2fr 1fr 1fr 0.8fr;
    font-size: 14px;
  }

  .image-list-header div:nth-child(3),
  .image-item .image-size {
    display: none;
  }

  .pagination-container {
    flex-direction: column;
    gap: 15px;
    align-items: center;
  }

  .pagination {
    flex-wrap: wrap;
    justify-content: center;
  }
}

@media (max-width: 480px) {
  .registry-header {
    padding: 20px 15px;
  }

  .registry-header h1 {
    font-size: 24px;
  }

  .registry-controls {
    padding: 20px 15px;
  }

  .image-list-container {
    padding: 15px;
  }

  .image-list-header, .image-item {
    grid-template-columns: 2fr 1fr 0.8fr;
    padding: 12px 15px;
  }

  .image-list-header div:nth-child(2),
  .image-item .image-tag {
    display: none;
  }
}
</style>

<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { useAuthStore } from '../stores/auth'
import axios from 'axios'

// 状态管理
const authStore = useAuthStore()
const loading = ref(false)
const images = ref<any[]>([])
const searchQuery = ref('')
const sizeFilter = ref('')
const selectedImage = ref<any>(null)
const deletingImages = ref(new Set())

// 分页状态
const currentPage = ref(1)
const pageSize = ref(20)
const totalImages = ref(0)
const totalPages = ref(0)

// Registry配置
const registryHost = ref('192.168.3.66:5000')

// 计算属性：当前页的数据（后端已经处理了分页和搜索）
const paginatedImages = computed(() => {
  return images.value
})

// 计算属性：可见的页码
const visiblePages = computed(() => {
  const pages = []
  const total = totalPages.value
  const current = currentPage.value

  if (total <= 7) {
    // 如果总页数小于等于7，显示所有页码
    for (let i = 1; i <= total; i++) {
      pages.push(i)
    }
  } else {
    // 总是显示第一页
    pages.push(1)

    if (current > 4) {
      pages.push('...')
    }

    // 显示当前页附近的页码
    const start = Math.max(2, current - 1)
    const end = Math.min(total - 1, current + 1)

    for (let i = start; i <= end; i++) {
      if (i !== 1 && i !== total) {
        pages.push(i)
      }
    }

    if (current < total - 3) {
      pages.push('...')
    }

    // 总是显示最后一页
    if (total > 1) {
      pages.push(total)
    }
  }

  return pages
})

// 获取镜像列表
const getImages = async () => {
  try {
    loading.value = true

    // 构建API参数
    const params = new URLSearchParams()
    if (searchQuery.value.trim()) {
      params.append('search', searchQuery.value.trim())
    }
    params.append('page', currentPage.value.toString())
    params.append('limit', pageSize.value.toString())

    const response = await axios.get(`/api/registry/images?${params.toString()}`, {
      headers: {
        'Authorization': `Bearer ${authStore.token}`
      }
    })

    if (response.data.data) {
      images.value = response.data.data || []

      // 更新分页信息
      if (response.data.pagination) {
        const pagination = response.data.pagination
        // 如果后端返回了分页信息，使用后端的分页
        totalImages.value = pagination.total
        totalPages.value = pagination.pages
      }
    } else {
      console.error('获取镜像列表失败:', response.data.error || '未知错误')
      images.value = []
    }
  } catch (error) {
    console.error('获取镜像列表错误:', error)

    // 如果是网络错误或认证错误，显示友好提示
    if (error.response?.status === 401) {
      alert('认证失败，请重新登录')
    } else if (error.response?.status === 503) {
      alert('镜像仓库服务不可用，请检查Registry连接')
    } else {
      alert('获取镜像列表失败，请稍后重试')
    }

    images.value = []
  } finally {
    loading.value = false
  }
}

// 搜索镜像
const searchImages = async () => {
  // 重置到第一页
  currentPage.value = 1
  // 重新获取数据
  await getImages()
}

// 分页方法
const goToPage = async (page: number) => {
  if (page >= 1 && page <= totalPages.value) {
    currentPage.value = page
    await getImages()
  }
}

// 处理每页大小变化
const handlePageSizeChange = async () => {
  currentPage.value = 1
  await getImages()
}

// 检查Registry健康状态
const checkRegistryHealth = async () => {
  try {
    const response = await axios.get('/api/registry/health', {
      headers: {
        'Authorization': `Bearer ${authStore.token}`
      }
    })

    if (response.data.status === 'ok') {
      console.log('Registry连接正常:', response.data.registry)
    } else {
      console.warn('Registry状态异常:', response.data.message)
    }
  } catch (error) {
    console.error('Registry健康检查失败:', error)
  }
}

// 上传镜像相关状态
const showUploadDialog = ref(false)
const uploadFile = ref<File | null>(null)
const uploading = ref(false)
const uploadProgress = ref(0)
const uploadEnvironment = ref<any>(null)
const dockerAvailable = ref(false)

// 检查上传环境
const checkUploadEnvironment = async () => {
  try {
    const response = await axios.get('/api/registry/upload/environment', {
      headers: {
        'Authorization': `Bearer ${authStore.token}`
      }
    })

    uploadEnvironment.value = response.data
    dockerAvailable.value = response.data.docker_available

    return response.data
  } catch (error) {
    console.error('检查上传环境失败:', error)
    dockerAvailable.value = false
    return null
  }
}

// 上传镜像
const uploadImage = async () => {
  // 先检查上传环境
  const env = await checkUploadEnvironment()

  if (!env || !env.docker_available) {
    alert(`❌ 上传功能不可用\n\n${env?.message || 'Docker服务不可用'}\n\n请联系管理员安装Docker服务`)
    return
  }

  showUploadDialog.value = true
}

// 选择文件
const handleFileSelect = (event: Event) => {
  const target = event.target as HTMLInputElement
  if (target.files && target.files.length > 0) {
    const file = target.files[0]

    // 检查文件类型
    const supportedFormats = uploadEnvironment.value?.supported_formats || ['.tar', '.tar.gz']
    const isValidFormat = supportedFormats.some(format => file.name.endsWith(format))

    if (!isValidFormat) {
      alert(`请选择支持的格式文件：${supportedFormats.join(', ')}`)
      return
    }

    // 检查文件大小
    const maxSize = uploadEnvironment.value?.max_file_size || (1024 * 1024 * 1024)
    if (file.size > maxSize) {
      alert(`文件大小超过限制：最大 ${formatSize(maxSize)}`)
      return
    }

    uploadFile.value = file
  }
}

// 执行上传
const performUpload = async () => {
  if (!uploadFile.value) {
    alert('请先选择要上传的镜像文件')
    return
  }

  uploading.value = true
  uploadProgress.value = 0

  try {
    const formData = new FormData()
    formData.append('image', uploadFile.value)

    const response = await axios.post('/api/registry/images/upload', formData, {
      headers: {
        'Authorization': `Bearer ${authStore.token}`,
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: (progressEvent) => {
        if (progressEvent.total) {
          uploadProgress.value = Math.round((progressEvent.loaded * 100) / progressEvent.total)
        }
      }
    })

    if (response.data.success) {
      alert(`✅ 镜像上传成功！\n\n镜像名称: ${response.data.image_name}\nRegistry名称: ${response.data.registry_name}`)

      // 关闭对话框并重置状态
      showUploadDialog.value = false
      uploadFile.value = null
      uploadProgress.value = 0

      // 刷新镜像列表
      await getImages()
    } else {
      alert('❌ 上传失败: ' + (response.data.error || '未知错误'))
    }
  } catch (error) {
    console.error('上传镜像错误:', error)

    if (error.response?.data?.error) {
      let errorMessage = '❌ 上传失败: ' + error.response.data.error

      // 添加详细信息和帮助
      if (error.response.data.details) {
        errorMessage += '\n\n详细信息: ' + error.response.data.details
      }
      if (error.response.data.help) {
        errorMessage += '\n\n💡 ' + error.response.data.help
      }

      alert(errorMessage)
    } else if (error.response?.status === 503) {
      alert('❌ 上传服务不可用\n\nDocker服务未安装或未运行，请联系管理员')
    } else {
      alert('❌ 上传失败，请检查网络连接和文件格式')
    }
  } finally {
    uploading.value = false
  }
}

// 取消上传
const cancelUpload = () => {
  showUploadDialog.value = false
  uploadFile.value = null
  uploadProgress.value = 0
  uploading.value = false
}

// 删除指定标签的镜像
const deleteImageTag = async (imageName: string, tag: string) => {
  const imageKey = `${imageName}:${tag}`

  if (!confirm(`确定要删除镜像标签 ${imageName}:${tag} 吗？\n\n注意：此操作不可撤销！`)) {
    return
  }

  // 添加到删除中的镜像集合
  deletingImages.value.add(imageKey)

  try {
    const params = new URLSearchParams()
    params.append('tag', tag)

    const response = await axios.delete(`/api/registry/images/${encodeURIComponent(imageName)}?${params.toString()}`, {
      headers: {
        'Authorization': `Bearer ${authStore.token}`
      }
    })

    if (response.data.success) {
      let message = '✅ ' + response.data.message
      if (response.data.note) {
        message += '\n\n💡 ' + response.data.note
      }
      alert(message)
      await getImages() // 刷新列表
    } else {
      alert('❌ 删除失败: ' + (response.data.error || '未知错误'))
    }
  } catch (error) {
    console.error('删除镜像标签错误:', error)

    if (error.response?.status === 404) {
      alert('❌ 镜像标签不存在')
    } else if (error.response?.status === 405) {
      alert('❌ Registry不支持删除操作\n\n请在Registry配置中启用删除功能：\n1. 设置环境变量 REGISTRY_STORAGE_DELETE_ENABLED=true\n2. 重启Registry服务')
    } else if (error.response?.data?.error) {
      alert('❌ 删除失败: ' + error.response.data.error)
    } else {
      alert('❌ 删除失败，请稍后重试')
    }
  } finally {
    // 从删除中的镜像集合中移除
    deletingImages.value.delete(imageKey)
  }
}

// 删除镜像（保留原方法以防其他地方使用）
const deleteImage = async (image: any) => {
  const tag = image.tags && image.tags.length > 0 ? image.tags[0] : 'latest'
  await deleteImageTag(image.name, tag)
}

// 拉取镜像
const pullImage = (image: any) => {
  const tag = image.tags[0] || 'latest'
  const command = `docker pull ${registryHost.value}/${image.name}:${tag}`

  // 复制命令到剪贴板
  navigator.clipboard.writeText(command).then(() => {
    alert(`拉取命令已复制到剪贴板:\n${command}`)
  }).catch(() => {
    alert(`请手动复制以下命令:\n${command}`)
  })
}

// 查看镜像详情
const viewImageDetail = (image: any) => {
  selectedImage.value = image
}

// 关闭镜像详情
const closeImageDetail = () => {
  selectedImage.value = null
}

// 复制Pull命令
const copyPullCommand = async (image: any, event: Event) => {
  const tag = image.tags[0] || 'latest'
  const command = `docker pull ${registryHost.value}/${image.name}:${tag}`
  
  try {
    await navigator.clipboard.writeText(command)
    
    // 显示复制成功提示
    const button = event.target as HTMLElement
    const originalText = button.textContent
    button.textContent = '已复制'
    button.classList.add('bg-green-600')
    
    setTimeout(() => {
      button.textContent = originalText
      button.classList.remove('bg-green-600')
    }, 2000)
  } catch (error) {
    console.error('复制失败:', error)
  }
}

// 刷新镜像列表
const refreshImages = () => {
  getImages()
}

// 格式化文件大小
const formatSize = (bytes: number) => {
  if (!bytes || bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB', 'TB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 格式化时间
const formatTime = (dateString: string) => {
  if (!dateString) return '-'

  try {
    const date = new Date(dateString)
    if (isNaN(date.getTime())) return '-'

    return date.toLocaleDateString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit'
    })
  } catch (error) {
    return '-'
  }
}

// 组件挂载时初始化
onMounted(async () => {
  // 检查Registry健康状态
  await checkRegistryHealth()
  // 检查上传环境
  await checkUploadEnvironment()
  // 获取镜像列表
  await getImages()
})
</script>

<style scoped>
/* 自定义样式 */
.btn {
  @apply px-4 py-2 rounded-lg font-medium transition-colors;
}

.btn-primary {
  @apply bg-blue-600 text-white hover:bg-blue-700;
}

.btn-sm {
  @apply px-3 py-1 text-sm;
}

.btn-disabled {
  @apply opacity-50 cursor-not-allowed;
}
</style>
